倒數一天!!!
今日任務: 倒數計時時鐘
倒計時我們可以使用setInterval(),每秒減1
setInterval(() => {
      seconds--;
}, 1000);
但是setInterval()在某些情況下會有失準的問題:當心 setInterval 因瀏覽器節流模式嚴重失準
因此下面我們每次執行都重新Date.now()取得現在時間,再將結束時間 - 現在時間來避免誤差情形發生。
Date.now(): 回傳自 1970/01/01 00:00:00 UTC 起經過的毫秒數。function timer(seconds) {
    const now = Date.now();
    const timeUp = now + seconds * 1000;
    setInterval(() => {
        const secondsLeft = (timeUp - Date.now()) / 1000;
        console.log(secondsLeft);
    }, 1000);
}
timer(10);
會有小數
使用Math.round() 函數回傳四捨五入後的近似值。
function timer(seconds) {
    const now = Date.now();
    const timeUp = now + seconds * 1000;
    setInterval(() => {
        const secondsLeft = Math.round((timeUp - Date.now()) / 1000);
        console.log(secondsLeft);
    }, 1000);
}
timer(10);

clearInterval(intervalID): 取消setInterval()的重複動作。
setInterval()會返回一個intervalID,我們將它存進變數countDown裡面,之後可以讓clearInterval()知道是要停止哪個setInterval()。
let countDown;
function timer(seconds) {
    const now = Date.now();
    const timeUp = now + seconds * 1000;
    countDown = setInterval(() => {
        const secondsLeft = Math.round((timeUp - Date.now()) / 1000);
        if(secondsLeft < 0){
            clearInterval(countDown);
            return;
        }
        console.log(secondsLeft);
    }, 1000);
}
setInterval()的定義是每[一段時間(毫秒)]執行一次,所以不會立刻執行,會停[一段時間]才開始執行。
此setInterval每1秒執行一次,會停1秒才開始執行,
我們希望一打開馬上開始執行,所以我們再開一個函式。
function timer(seconds) {
    const now = Date.now();
    const timeUp = now + seconds * 1000;
    displayTimeLeft(seconds);
    countDown = setInterval(() => {
        const secondsLeft = Math.round((timeUp - Date.now()) / 1000);
        if (secondsLeft < 0) {
            clearInterval(countDown);
            return;
        }
        displayTimeLeft(secondsLeft);
    }, 1000);
}
function displayTimeLeft(seconds){
    console.log(seconds);
}
timer(10);

const timeLeft = document.querySelector('.display__time-left');
function displayTimeLeft(seconds){
  const mins = Math.floor(seconds / 60);
  const remainderSecs = seconds % 60;
  timeLeft.textContent = `${mins}:${remainderSecs}`;
}

function displayTimeLeft(seconds){
  const mins = Math.floor(seconds / 60);
  const remainderSecs = seconds % 60;
  timeLeft.textContent = `${mins}:${remainderSecs < 10 ? '0' : ''}${remainderSecs}`;
}
Document.title: 設置網頁的標題
function displayTimeLeft(seconds){
    ...
    const display = `${mins}:${remainderSecs < 10 ? '0' : ''}${remainderSecs}`;
    timeLeft.textContent = display;
    document.title = display;
}
new date(milliseconds):傳入的參數是一個數字,值表示從 1970-01-01 00:00:00 UTC (格林威治標準時間) 開始累計到某時間點的毫秒數 (milliseconds)。
Date.prototype.getHours(): 根據本地時間返回指定日期的小時 ( 0-23 )。Date.prototype.getMinutes(): 根據本地時間返回指定日期的分鐘 ( 0-59 )。
const endTime = document.querySelector('.display__end-time');
function timer(seconds) {
    ...
    displayTimeLeft(seconds);
    diplayEndTime(timeUp);
    countDown = setInterval(() => {
        ...
    }, 1000);
}
function diplayEndTime(timeUp) {
    const end = new Date(timeUp);
    const hours = end.getHours();
    const mins = end.getMinutes();
    endTime.textContent = `結束時間:${hours}:${mins < 10 ? '0' : ''}${mins}`;
}

function diplayEndTime(timeUp) {
    const end = new Date(timeUp);
    const hours = end.getHours();
    const mins = end.getMinutes();
    const AmPmHours = hours < 12 ? `上午${hours}` : `下午${hours - 12}`;
    endTime.textContent = `結束時間:${AmPmHours}:${mins < 10 ? '0' : ''}${mins}`;
}
const timeBtns = document.querySelectorAll('[data-time]');
timeBtns.forEach((btn) => btn.addEventListener('click', startTimer));
function startTimer() {
    const seconds = parseInt(this.dataset.time); //將dataset字串轉成數字
    timer(seconds);
}
連續按按鈕畫面會亂閃,setInterval()太多個,開頭先清除掉所有setInterval
function timer(seconds) {
    clearInterval(countDown); //開頭先清除掉所有setInterval
    
    const now = Date.now();
    const timeUp = now + seconds * 1000;
    displayTimeLeft(seconds);
    diplayEndTime(timeUp);
    countDown = setInterval(() => {
        ...
    }, 1000);
}
Document.forms:
<form>元素的列表。const selectForm = document.forms[index];
const selectFormElement = document.forms[index].elements[index];
document.forms.customForm:取得表單名稱為customForm的表單集合
e.preventDefault():如果事件可以被取消,就取消事件(即取消事件的預設行為)。但不會影響事件的傳遞,事件仍會繼續傳遞。
document.customForm.addEventListener('submit', inputTime);
function inputTime(e) {
    e.preventDefault();
    const secs = this.minutes.value * 60; //將輸入的數字分鐘數轉成秒數
    timer(secs);
    this.reset(); //清空表單
}
今日學習到的:
setInterval():
intervalID,之後可以讓clearInterval()知道是要停止哪個setInterval()。clearInterval(intervalID): 取消setInterval()的重複動作。Date.now(): 回傳自 1970/01/01 00:00:00 UTC 起經過的毫秒數。new date(milliseconds):傳入的參數是一個數字,值表示從 1970-01-01 00:00:00 UTC (格林威治標準時間) 開始累計到某時間點的毫秒數 (milliseconds)。Date.prototype.getHours(): 根據本地時間返回指定日期的小時 ( 0-23 )。Date.prototype.getMinutes(): 根據本地時間返回指定日期的分鐘 ( 0-59 )。Math.round() 函數回傳四捨五入後的近似值。Document.title: 設置網頁的標題Document.forms:
<form>元素的列表。document.forms.customForm:取得表單名稱為customForm的表單集合e.preventDefault():如果事件可以被取消,就取消事件(即取消事件的預設行為)。但不會影響事件的傳遞,事件仍會繼續傳遞。效果連結:連結
參考連結:
MDN: Date
JavaScript Date 時間和日期 - Fooish 程式技術
MDN: Document.forms
JavaScript - 表單元素- Form Element - KingKong Bruce記事
MDN: Event.preventDefault()
JS30